package io.renren.sf.controller;

import com.alibaba.fastjson.JSONObject;
import com.hz.common.utils.ResponseData;
import com.hz.common.utils.ResponsePage;
import com.hz.utils.FixedInformationName;
import io.renren.common.utils.*;
import io.renren.sf.entity.*;
import io.renren.sf.feign.OssFeign;
import io.renren.sf.service.*;
import io.renren.sf.vo.*;
import io.swagger.annotations.*;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * @author cyl_txw
 * @email cyl_txw@gmail.com
 * @date 2023-05-09 15:02:11
 */
@RestController
@RequestMapping("sf/copyingSteleCalligraphy")
@Api(tags = "临摹碑帖管理")
public class    CopyingSteleCalligraphyController {
    @Autowired
    private HzFixedInformationDicService fixedInformationDicService;

    @Autowired
    private HzCopyingSteleCalligraphyService copyingSteleCalligraphyService;

    @Autowired
    private HzCopyingSteleCalligraphyCharacterService copyingSteleCalligraphyCharacterService;

    @Autowired
    private RecommendSteleCalligraphyCollectionService recommendSteleCalligraphyCollectionService;

    @Autowired
    private RecommendSteleCalligraphyService recommendSteleCalligraphyService;

    @Autowired
    private CopyingSteleCalligraphySinglepageService copyingSteleCalligraphySinglepageService;

    @Autowired
    private OssFeign ossFeign;


    /**
     * 批量上传临摹碑帖资源
     */
    @ApiOperation("批量上传临摹碑帖资源")
    @PostMapping(value = "/calligraphyResource/upload", headers = "content-type=multipart/form-data")
    public ResponseData calligraphyResourceUpload(
            @ApiParam(value = "copybookResourceZip", required = true) MultipartFile copybookResourceZip) throws Exception {
        String timeMd5 = com.hz.utils.MD5.encrypt(new Date().getTime() + "");
        String dirPath = Constant.ZipCalligraphyResource.PATH.getName() + timeMd5;  // 压缩文件处理的路径
        String zipPath = dirPath + "/" + Constant.ZipCalligraphyResource.ZIPNAME.getName() + ".zip";  // 压缩包文件路径
        String descDir = dirPath + "/" + Constant.ZipCalligraphyResource.ZIPNAME.getName();  // 解压缩文件夹
        try {
            // 1检验资源是否符合要求
            // 文件大小校验
            // 2解压压缩包
            // 临时文件路径
            File copybookResourceTmpZip = new File(zipPath);
            FileUtils.copyInputStreamToFile(copybookResourceZip.getInputStream(), copybookResourceTmpZip);
            CompressUtil.decompress(zipPath, descDir);
            // CompressUtil.decompress("C:\\Users\\xw\\Desktop\\a\\字帖资源模板.zip");
            // 读取解压的文件
            // 新增碑帖--新增碑帖单页--批量新增碑帖字list
            File file = new File(descDir);  // 解压缩的文件夹路径
            File[] calligraphyDirs = file.listFiles();
            for (File calligraphyDir : calligraphyDirs) {
                // 如果是文件直接pass
                if (calligraphyDir.isFile())
                    continue;
                String calligraphyName = calligraphyDir.getName();  // 字帖字的名字
                // 读取碑帖的txt信息文档
                List<String> inforLines = Files.lines(Paths.get(descDir + "/" + calligraphyName + ".txt")).collect(Collectors.toList());
                // 如果行数小于8行或前8行有一行不包含：符号则flag标志为false，直接pass当前碑帖
                boolean flag = true;
                if (inforLines.size() < 8){
                    flag = false;
                }else {
                    for (String inforLine : inforLines)
                        if (!inforLine.contains("：")){
                             flag = false;
                             break;
                        }
                }
                if (!flag)  continue;
                // 检测信息内容
                // 如果碑帖图片在改文件不存在、年代、书体、书家不存在
                String picFileName = inforLines.get(0).split("：")[1];
                File steleCalligraphyFile = new File(descDir + "/" + picFileName);
                if (!steleCalligraphyFile.exists()) continue;
                String steleCalligraphyName = inforLines.get(1).split("：")[1];
                String calligraphyIntro = inforLines.get(2).split("：")[1];
                String calligrapherIntro = inforLines.get(3).split("：")[1];
                String years = inforLines.get(4).split("：")[1];
                String style = inforLines.get(5).split("：")[1];
                String calligrapher = inforLines.get(6).split("：")[1];
                String sorderStr = inforLines.get(7).split("：")[1];
                Long yid = fixedInformationDicService.getIdByTypeAndName(years, FixedInformationName.CO_ST_CALLI_YEARS);
                Long sid = fixedInformationDicService.getIdByTypeAndName(style, FixedInformationName.CO_ST_CALLI_STYLE);
                Long cid = fixedInformationDicService.getIdByTypeAndName(calligrapher, FixedInformationName.CO_ST_CALLI_CALLIGRAPHER);
                // 判断顺序是否可以转成数字
                Integer sorder;
                try {
                    sorder = Integer.parseInt(sorderStr);
                    // 上传封面
                    R upload = ossFeign.uploadZip(steleCalligraphyFile.getAbsolutePath());
                    String steleCalligraphySrc = (String) upload.get("url");
                    // 制作缩略图
                    String steleCalligraphyThumbnailSrc = getThumbnailUrl(steleCalligraphySrc);
                    if (steleCalligraphyThumbnailSrc.equals(""))    continue;

                    HzCopyingSteleCalligraphyEntity hzCopyingSteleCalligraphy = new HzCopyingSteleCalligraphyEntity(steleCalligraphySrc,
                            steleCalligraphyThumbnailSrc,
                            steleCalligraphyName,
                            calligraphyIntro,
                            calligrapherIntro,
                            years,
                            style,
                            calligrapher,
                            sorder,
                            new Date(),
                            yid,
                            sid,
                            cid);
                    copyingSteleCalligraphyService.save(hzCopyingSteleCalligraphy);
                    // 新增碑帖单页
                    // 遍历单元列表-只能是文件夹
                    File[] steleCalligraphySinglepageFiles = calligraphyDir.listFiles();
                    int order = 1;
                    for (File steleCalligraphySinglepageFile : steleCalligraphySinglepageFiles){
                        if (!steleCalligraphySinglepageFile.isDirectory())
                            continue;
                        String singlepageName = steleCalligraphySinglepageFile.getName();
                        // 单页图只支持png和jpg格式
                        File singelePicFile = new File(descDir + "/" + calligraphyName + "/" + singlepageName + ".jpg");
                        if (!singelePicFile.exists())
                            singelePicFile = new File(descDir + "/" + calligraphyName + "/" + singlepageName + ".png");
                        // 上传碑帖单页图
                        String steleCalligraphySinglepageUrl = "";
                        try {
                            upload = ossFeign.uploadZip(singelePicFile.getAbsolutePath());
                            steleCalligraphySinglepageUrl = (String) upload.get("url");

                            CopyingSteleCalligraphySinglepageEntity copyingSteleCalligraphySinglepage = new CopyingSteleCalligraphySinglepageEntity(
                                    singlepageName,
                                    steleCalligraphySinglepageUrl,
                                    hzCopyingSteleCalligraphy.getId(),
                                    order++
                            );
                            copyingSteleCalligraphySinglepageService.save(copyingSteleCalligraphySinglepage);
                            // 批量上传单页下的碑帖字
                            File steleCalligraphyCharacterDir = new File(descDir + "/" + calligraphyName + "/" + singlepageName);
                            if (!steleCalligraphyCharacterDir.isDirectory())    continue;
                            File[] steleCalligraphyCharacterFiles = steleCalligraphyCharacterDir.listFiles();
                            List<HzCopyingSteleCalligraphyCharacterEntity> steleCalliCaracterList = new ArrayList<>();
                            Long id = copyingSteleCalligraphySinglepage.getSid();
                            int corder = 1;
                            for (File steleCalligraphyCharacterFile : steleCalligraphyCharacterFiles){
                                if (!steleCalligraphyCharacterFile.isFile())
                                    continue;
                                String steleCalligraphyCharacterUrl = "";
                                try {
                                    upload = ossFeign.uploadZip(steleCalligraphyCharacterFile.getAbsolutePath());
                                    steleCalligraphyCharacterUrl = (String) upload.get("url");
                                }catch (Exception e){
                                    continue;
                                }
                                // 新增碑帖字记录
                                HzCopyingSteleCalligraphyCharacterEntity steleCalligraphyCharacter = new HzCopyingSteleCalligraphyCharacterEntity(
                                        steleCalligraphyCharacterUrl,
                                        copyingSteleCalligraphySinglepage.getId(),
                                        corder++);
                                steleCalliCaracterList.add(steleCalligraphyCharacter);
                            }
                            // 清除之前相关的数据，重新添加
                            copyingSteleCalligraphyCharacterService.removeCaracterBySid(id);
                            // 批量插入数据库
                            copyingSteleCalligraphyCharacterService.saveBatch(steleCalliCaracterList);
                        }catch (Exception e){
                            continue;
                        }
                    }
                } catch (Exception e) {
                    continue;
                }
            }
        } catch (Exception e){
            return ResponseData.error(500, "解压缩包出现错误");
        }finally {
            System.gc();
            System.runFinalization(); // 强制回收io流
            // 删除文件夹下的所有文件
            File dir = new File(dirPath);
            try {
                FileUtils.forceDelete(dir);
            }catch (Exception e){
                return ResponseData.error(500, "删除文件失败");
            }
        }
        return ResponseData.success("资源上传成功");
    }


    /**
     * 推荐碑帖集合分页查询
     */
    @ApiOperation("推荐碑帖集合分页查询")
    @PostMapping("/restelecallicollection/page")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "curPage", value = "当前页数", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "rtype", value = "种类。1推荐临摹碑帖2推荐欣赏碑帖,可用值:1,2", paramType = "query", allowableValues = "1,2", dataType = "int", required = true)
    })
    public ResponseData<ResponsePage<List<RecommendSteleCalligraphyCollectionEntity>>> restelecallicollectionPage(@RequestParam("curPage") Integer curPage,
                                                                                                                  @RequestParam("pageSize") Integer pageSize,
                                                                                                                  @RequestParam("rtype") Integer rtype) {
        List<RecommendSteleCalligraphyCollectionEntity> reSteleCalliCollectionList = recommendSteleCalligraphyCollectionService.queryCollections(curPage, pageSize, rtype);

        ResponsePage<List<RecommendSteleCalligraphyCollectionEntity>> page = new ResponsePage<>(
                reSteleCalliCollectionList,
                recommendSteleCalligraphyCollectionService.queryCollectionsNum(rtype),
                pageSize
        );
        return ResponseData.success(page);
    }


    /**
     * 推荐碑帖集合保存
     */
    @ApiOperation("推荐碑帖集合保存")
    @PostMapping("/restelecallicollection/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "steleCalligraphyConame", value = "推荐碑帖集合名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "rtype", value = "种类。1推荐临摹碑帖2推荐欣赏碑帖,可用值:1,2", paramType = "query", allowableValues = "1,2", dataType = "int", required = true),
            @ApiImplicitParam(name = "rorder", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData restelecallicollectionSave(@RequestParam("steleCalligraphyConame") String steleCalligraphyConame,
                                                   @RequestParam("rtype") int rtype,
                                                   @RequestParam("rorder") int rorder) {
        RecommendSteleCalligraphyCollectionEntity reSteleCalliCollection = new RecommendSteleCalligraphyCollectionEntity(steleCalligraphyConame, rtype, rorder, new Date());
        recommendSteleCalligraphyCollectionService.save(reSteleCalliCollection);
        return ResponseData.success("保存成功");
    }

    /**
     * 推荐碑帖集合删除
     */
    @ApiOperation("推荐碑帖集合删除")
    @PostMapping("/restelecallicollection/delete")
    public ResponseData restelecallicollectionDelete(@RequestBody Long[] ids) {
        recommendSteleCalligraphyCollectionService.removeByIds(Arrays.asList(ids));
        return ResponseData.success("删除成功");
    }

    /**
     * 推荐碑帖集合修改
     */
    @ApiOperation("推荐碑帖集合修改")
    @PostMapping("/restelecallicollection/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "推荐碑帖集合id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "steleCalligraphyConame", value = "推荐碑帖集合名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "rtype", value = "种类。1推荐临摹碑帖2推荐欣赏碑帖,可用值:1,2", paramType = "query", allowableValues = "1,2", dataType = "int", required = true),
            @ApiImplicitParam(name = "rorder", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData restelecallicollectionUpdate(@RequestParam("id") Long id,
                                                     @RequestParam("steleCalligraphyConame") String steleCalligraphyConame,
                                                     @RequestParam("rtype") int rtype,
                                                     @RequestParam("rorder") int rorder) {
        RecommendSteleCalligraphyCollectionEntity reSteleCalliCollection = new RecommendSteleCalligraphyCollectionEntity(
                id,
                steleCalligraphyConame,
                rtype,
                rorder);
        recommendSteleCalligraphyCollectionService.updateById(reSteleCalliCollection);
        return ResponseData.success("修改成功");
    }


    /**
     * 推荐碑帖保存
     */
    @ApiOperation("推荐碑帖保存")
    @PostMapping("/restelecalligraphy/save")
    public ResponseData restelecalligraphySave(@RequestBody ReSteleCalligraphyVo reSteleCalligraphyVo) {
        Long rid = reSteleCalligraphyVo.getRid();
        List<Long> sidList = reSteleCalligraphyVo.getSidList();
        List<HzCopyingSteleCalligraphyEntity> copyingSteleCalligraphyList = copyingSteleCalligraphyService.findByIds(sidList);
        List<RecommendSteleCalligraphyEntity> recommendSteleCalligraphyList = new ArrayList<>();
        // 封装
        int maxOldSorder = recommendSteleCalligraphyService.findSorderMax(rid);
        for (HzCopyingSteleCalligraphyEntity copyingSteleCalligraphy:copyingSteleCalligraphyList) {
            RecommendSteleCalligraphyEntity recommendSteleCalligraphy = new RecommendSteleCalligraphyEntity(
                    copyingSteleCalligraphy.getSteleCalligraphy(),
                    copyingSteleCalligraphy.getSteleCalligraphyThumbnail(),
                    copyingSteleCalligraphy.getId(),
                    rid,
                    copyingSteleCalligraphy.getSteleCalligraphyName(),
                    copyingSteleCalligraphy.getCalligraphyIntroduction(),
                    copyingSteleCalligraphy.getCalligrapherIntroduction(),
                    ++maxOldSorder,
                    new Date()
            );
            recommendSteleCalligraphyList.add(recommendSteleCalligraphy);
        }
        // 保存
        recommendSteleCalligraphyService.saveBatch(recommendSteleCalligraphyList);
        return ResponseData.success("保存成功");
    }

    /**
     * 推荐碑帖删除
     */
    @ApiOperation("推荐碑帖删除")
    @PostMapping("/restelecalligraphy/delete")
    public ResponseData restelecalligraphyDelete(@RequestBody Long[] ids) {
        recommendSteleCalligraphyService.removeByIds(Arrays.asList(ids));
        return ResponseData.success("删除成功");
    }

    /**
     * 推荐碑帖修改
     */
    @ApiOperation("推荐碑帖修改")
    @PostMapping("/restelecalligraphy/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "推荐碑帖id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "sorder", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData restelecalligraphyUpdate(@RequestParam("id") Long id,
                                                 @RequestParam("sorder") int sorder) {
        RecommendSteleCalligraphyEntity recommendSteleCalligraphy = new RecommendSteleCalligraphyEntity(id, sorder);
        recommendSteleCalligraphyService.updateById(recommendSteleCalligraphy);
        return ResponseData.success("修改成功");
    }



    /**
     * 临摹碑帖所有年代、书体、书家获取
     */
    @ApiOperation("临摹碑帖所有年代、书体、书家获取")
    @GetMapping("/ysc/get")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "查询类别。1年代，2书体，3书家", paramType = "query", dataType = "Integer", allowableValues = "1,2,3", required = true)
    })
    public ResponseData yscGet(@RequestParam("type") Integer type) {
        // 查询所有的年代、书体、书家名称
        List<HzFixedInformationDicEntity> fixedInformationDicList;
        // 映射成vo List
        switch (type){
            case 1 :
                fixedInformationDicList = fixedInformationDicService.queryByName(FixedInformationName.CO_ST_CALLI_YEARS);
                List<CopyingSteleCalligraphyYearsVo> copyingSteleCalligraphyYearsList = fixedInformationDicList.stream()
                        .map(fixedInformationDic -> new CopyingSteleCalligraphyYearsVo(fixedInformationDic.getId(),
                                fixedInformationDic.getFixedInformationContent(),
                                fixedInformationDic.getUpdatetime(),
                                fixedInformationDic.getIorder()))
                        .collect(Collectors.toList());
                return ResponseData.success(copyingSteleCalligraphyYearsList);
            case 2 :
                fixedInformationDicList = fixedInformationDicService.queryByName(FixedInformationName.CO_ST_CALLI_STYLE);
                List<CopyingSteleCalligraphyStyleVo> copyingSteleCalligraphyStyleList = fixedInformationDicList.stream()
                        .map(fixedInformationDic -> new CopyingSteleCalligraphyStyleVo(fixedInformationDic.getId(),
                                fixedInformationDic.getFixedInformationContent(),
                                fixedInformationDic.getUpdatetime(),
                                fixedInformationDic.getIorder()))
                        .collect(Collectors.toList());
                return ResponseData.success(copyingSteleCalligraphyStyleList);
            case 3 :
                fixedInformationDicList = fixedInformationDicService.queryByName(FixedInformationName.CO_ST_CALLI_CALLIGRAPHER);
                List<CopyingSteleCalligraphyCalligrapherVo> copyingStCalliCalligrapherList = fixedInformationDicList.stream()
                        .map(fixedInformationDic -> new CopyingSteleCalligraphyCalligrapherVo(fixedInformationDic.getId(),
                                fixedInformationDic.getFixedInformationContent(),
                                fixedInformationDic.getUpdatetime(),
                                fixedInformationDic.getIorder()))
                        .collect(Collectors.toList());
                return ResponseData.success(copyingStCalliCalligrapherList);
        }
        return ResponseData.success("类别参数错误！", false);
    }

    /**
     * 碑帖字列表查询
     */
    @ApiOperation("碑帖字列表查询")
    @PostMapping("/stelecallicharacter/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sid", value = "碑帖单页id", paramType = "query", dataType = "Long", required = true),
    })
    public ResponseData<List<HzCopyingSteleCalligraphyCharacterEntity>> stelecallicharacterList(@RequestParam("sid") long sid){
        List<HzCopyingSteleCalligraphyCharacterEntity> copyingSteleCalliCharacterList =  copyingSteleCalligraphyCharacterService.getBySid(sid);
        return ResponseData.success(copyingSteleCalliCharacterList);
    }

    /**
     * 碑帖字列表修改、保存
     */
    @ApiOperation("碑帖字列表修改、保存")
    @PostMapping("/stelecallicharacter/updatesave")
    public ResponseData stelecallicharacterUpdatesave(@RequestBody SteleCalligraphySinglepageVo steleCalligraphySinglepageVo){
        // 清除之前相关的数据，重新添加
        Long sid = steleCalligraphySinglepageVo.getSid();
        copyingSteleCalligraphyCharacterService.removeCaracterBySid(sid);
        List<SteleCalligraphyCaracterVo> steleCalliCaracterVoList = steleCalligraphySinglepageVo.getSteleCalligraphyCaracterVoList();
        // 重新添加
        AtomicInteger index = new AtomicInteger(0);
        List<HzCopyingSteleCalligraphyCharacterEntity> steleCalligraphyCaracterList = steleCalliCaracterVoList.stream()
                .map(steleCalligraphyCaracterVo -> new HzCopyingSteleCalligraphyCharacterEntity(
                        steleCalligraphyCaracterVo.getSteleCalligraphyCharacter(),
                        steleCalligraphyCaracterVo.getSid(),
                        index.addAndGet(1)))
                .collect(Collectors.toList());
        // 批量插入数据库
        copyingSteleCalligraphyCharacterService.saveBatch(steleCalligraphyCaracterList);
        return ResponseData.success("保存成功");
    }

    /**
     * 碑帖修改
     */
    @ApiOperation("碑帖单页修改")
    @PostMapping("/stelecalligraphysinglepage/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "碑帖单页id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "steleCalligraphySinglepageName", value = "临摹碑帖单页名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "steleCalligraphySinglepage", value = "临摹碑帖单页src", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "sid", value = "临摹碑帖id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "sorder", value = "顺序", paramType = "query", dataType = "Integer", required = true)
    })
    public ResponseData stelecalligraphysinglepageUpdate(@RequestParam("id") long id,
                                                         @RequestParam("steleCalligraphySinglepageName") String steleCalligraphySinglepageName,
                                                         @RequestParam("steleCalligraphySinglepage") String steleCalligraphySinglepage,
                                                         @RequestParam("sid") Long sid,
                                                         @RequestParam("sorder") int sorder){
        CopyingSteleCalligraphySinglepageEntity copyingSteleCalligraphySinglepage = new CopyingSteleCalligraphySinglepageEntity(
                id,
                steleCalligraphySinglepageName,
                steleCalligraphySinglepage,
                sid,
                sorder
        );
        copyingSteleCalligraphySinglepageService.updateById(copyingSteleCalligraphySinglepage);
        return ResponseData.success("修改成功");
    }

    /**
     * 碑帖单页保存
     */
    @ApiOperation("碑帖单页保存")
    @PostMapping("/stelecalligraphysinglepage/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "steleCalligraphySinglepageName", value = "临摹碑帖单页名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "steleCalligraphySinglepage", value = "临摹碑帖单页src", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "sid", value = "临摹碑帖id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "sorder", value = "顺序", paramType = "query", dataType = "Integer", required = true)
    })
    public ResponseData stelecalligraphysinglepageSave(@RequestParam("steleCalligraphySinglepageName") String steleCalligraphySinglepageName,
                                                       @RequestParam("steleCalligraphySinglepage") String steleCalligraphySinglepage,
                                                       @RequestParam("sid") long sid,
                                                       @RequestParam("sorder") int sorder) {
        CopyingSteleCalligraphySinglepageEntity copyingSteleCalligraphySinglepage = new CopyingSteleCalligraphySinglepageEntity(
                steleCalligraphySinglepageName,
                steleCalligraphySinglepage,
                sid,
                sorder
        );
        copyingSteleCalligraphySinglepageService.save(copyingSteleCalligraphySinglepage);
        return ResponseData.success("保存成功");
    }

    /**
     * 碑帖单页列表删除
     */
    @ApiOperation("碑帖单页列表删除")
    @PostMapping("/stelecalligraphysinglepage/delete")
    public ResponseData stelecalligraphysinglepageDelete(@RequestBody Long[] ids){
        copyingSteleCalligraphySinglepageService.removeByIds(Arrays.asList(ids));
        return ResponseData.success("删除成功");
    }

    /**
     * 碑帖保存
     */
    @ApiOperation("碑帖保存")
    @PostMapping("/stelecalligraphy/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "steleCalligraphySrc", value = "临摹碑帖src", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "steleCalligraphyName", value = "临摹碑帖名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "calligraphyIntro", value = "碑帖简介", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "calligrapherIntro", value = "书家介绍", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "yid", value = "年代id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "sid", value = "书体id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "cid", value = "书家id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData stelecalligraphySave(@RequestParam("steleCalligraphySrc") String steleCalligraphySrc,
                                  @RequestParam("steleCalligraphyName") String steleCalligraphyName,
                                  @RequestParam("calligraphyIntro") String calligraphyIntro,
                                  @RequestParam("calligrapherIntro") String calligrapherIntro,
                                  @RequestParam("yid") long yid,
                                  @RequestParam("sid") long sid,
                                  @RequestParam("cid") long cid,
                                  @RequestParam("order") int order) {
        List<HzFixedInformationDicEntity> fixedInformationDicList = fixedInformationDicService.findByIds(yid, sid, cid);
        if(fixedInformationDicList.size() != 3) return ResponseData.success("保存失败，请重试！",false);
        // 制作缩略图
        String steleCalligraphyThumbnailSrc = getThumbnailUrl(steleCalligraphySrc);
        if (steleCalligraphyThumbnailSrc.equals(""))    return ResponseData.error(500, "保存失败，缩略图制作失败！");

        HzCopyingSteleCalligraphyEntity hzCopyingSteleCalligraphy = new HzCopyingSteleCalligraphyEntity(steleCalligraphySrc,
                steleCalligraphyThumbnailSrc,
                steleCalligraphyName,
                calligraphyIntro,
                calligrapherIntro,
                fixedInformationDicList.get(0).getFixedInformationContent(),
                fixedInformationDicList.get(1).getFixedInformationContent(),
                fixedInformationDicList.get(2).getFixedInformationContent(),
                order,
                new Date(),
                yid,
                sid,
                cid);
        copyingSteleCalligraphyService.save(hzCopyingSteleCalligraphy);
        return ResponseData.success("保存成功");
    }

    /**
     * 创建缩略图
     * 下载原图-制作缩略图-上传-获取缩略图地址
     * @param picUrl
     * @return
     */
    private String getThumbnailUrl(String picUrl){
        String suffix = picUrl.substring(picUrl.lastIndexOf("."));
        String md5 = MD5.encrypt(picUrl);
        String savePath = "/tmp/steleCalligraphy/";
        // 下载原图
        Download.download(picUrl, md5 + suffix, savePath);
        // 制作缩略图
        String originalDrawingUrl = savePath + md5 + suffix;
        String thumbnailUrl = savePath + md5 + "_thumbnail" + suffix;
        File originalDrawing = new File(originalDrawingUrl);
        try {
            Thumbnails.of(originalDrawing)
                    //缩小到30%
                    .scale(0.3)
                    //指定图片类型是支持Alpha通道
                    .imageType(BufferedImage.TYPE_INT_ARGB)
                    //将生成的缩略图写入文件
                    .toFile(new File(thumbnailUrl));
        }catch (IOException e){
            // 返回失败结果
            return "";
        }finally {
            // 移除原图本地临时文件
            if(originalDrawing.exists())    originalDrawing.delete();
        }
        // 上传到oss并获取缩略图地址
        R upload = ossFeign.uploadZip(thumbnailUrl);
        String thumbnailOssSrc = (String) upload.get("url");
        // 移除缩略图本地临时文件
        File thumbnail = new File(thumbnailUrl);
        if(thumbnail.exists())  thumbnail.delete();
        return thumbnailOssSrc;
    }

    /**
     * 碑帖修改
     */
    @ApiOperation("碑帖修改")
    @PostMapping("/stelecalligraphy/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "临摹碑帖id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "steleCalligraphySrc", value = "临摹碑帖src", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "steleCalligraphyName", value = "临摹碑帖名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "calligraphyIntro", value = "碑帖简介", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "calligrapherIntro", value = "书家介绍", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "yid", value = "年代id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "sid", value = "书体id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "cid", value = "书家id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData stelecalligraphyUpdate(@RequestParam("id") long id,
                                    @RequestParam("steleCalligraphySrc") String steleCalligraphySrc,
                                    @RequestParam("steleCalligraphyName") String steleCalligraphyName,
                                    @RequestParam("calligraphyIntro") String calligraphyIntro,
                                    @RequestParam("calligrapherIntro") String calligrapherIntro,
                                    @RequestParam("yid") long yid,
                                    @RequestParam("sid") long sid,
                                    @RequestParam("cid") long cid,
                                    @RequestParam("order") int order){
        List<HzFixedInformationDicEntity> fixedInformationDicList = fixedInformationDicService.findByIds(yid, sid, cid);
        if(fixedInformationDicList.size() != 3) return ResponseData.success("修改失败，请重试！",false);

        HzCopyingSteleCalligraphyEntity oleCopyingSteleCalligraphy = copyingSteleCalligraphyService.getById(id);
        if (oleCopyingSteleCalligraphy == null){
            ResponseData.success("修改失败",false);
        }
        String steleCalligraphyThumbnailSrc = oleCopyingSteleCalligraphy.getSteleCalligraphyThumbnail();
        if(oleCopyingSteleCalligraphy.getSteleCalligraphy() != steleCalligraphySrc) {
            // 重新制作缩略图
            steleCalligraphyThumbnailSrc = getThumbnailUrl(steleCalligraphySrc);
        }

        HzCopyingSteleCalligraphyEntity hzCopyingSteleCalligraphy = new HzCopyingSteleCalligraphyEntity(id,
                steleCalligraphySrc,
                steleCalligraphyThumbnailSrc,
                steleCalligraphyName,
                calligraphyIntro,
                calligrapherIntro,
                fixedInformationDicList.get(0).getFixedInformationContent(),
                fixedInformationDicList.get(1).getFixedInformationContent(),
                fixedInformationDicList.get(2).getFixedInformationContent(),
                order,
                new Date(),
                yid,sid,cid);
        copyingSteleCalligraphyService.updateById(hzCopyingSteleCalligraphy);
        return ResponseData.success("修改成功");
    }

    /**
     * 碑帖列表删除
     */
    @ApiOperation("碑帖列表删除")
    @PostMapping("/stelecalligraphy/delete")
    public ResponseData stelecalligraphyDelete(@RequestBody Long[] ids){
        copyingSteleCalligraphyService.removeByIds(Arrays.asList(ids));
        return ResponseData.success("删除成功");
    }

    /**
     * 碑帖分页列表
     */
    @ApiOperation("碑帖分页列表")
    @GetMapping("/stelecalligraphy/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "curPage", value = "当前页数", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "condition", value = "模糊查询条件", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "years", value = "年代", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "style", value = "书体", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "calligrapher", value = "书家", paramType = "query", dataType = "String", required = false)
    })
    public ResponseData<ResponsePage<List<HzCopyingSteleCalligraphyEntity>>> stelecalligraphyPage(@RequestParam("curPage") Integer curPage,
                                                                                                  @RequestParam("pageSize") Integer pageSize,
                                                                                                  @RequestParam(value = "condition",required = false) String condition,
                                                                                                  @RequestParam(value = "years",required = false) String years,
                                                                                                  @RequestParam(value = "style",required = false) String style,
                                                                                                  @RequestParam(value = "calligrapher",required = false) String calligrapher) {

        List<HzCopyingSteleCalligraphyEntity> copyingSteleCalligraphyList =copyingSteleCalligraphyService.querySteleCalligraphy(curPage, pageSize, years, style, calligrapher, condition);

        ResponsePage<List<HzCopyingSteleCalligraphyEntity>> page = new ResponsePage<>(copyingSteleCalligraphyList,
                copyingSteleCalligraphyService.querySteleCalligraphyNum(years, style, calligrapher, condition),
                pageSize);
        return ResponseData.success(page);
    }

    /**
     * 年代保存
     */
    @ApiOperation("年代保存")
    @PostMapping("/years/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "years", value = "年代名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData yearsSave(@RequestParam("years") String years,
                                  @RequestParam("order") int order){
        // 年代名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_YEARS, years);
        if (inforDicList.size() > 0)    return ResponseData.success("保存失败，年代名称不能重复！",false);

        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(FixedInformationName.CO_ST_CALLI_YEARS, years, new Date(), order);
        fixedInformationDicService.save(fixedInformationDic);
        return ResponseData.success("保存成功");
    }

    /**
     * 年代修改
     */
    @ApiOperation("年代修改")
    @PostMapping("/years/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "年代id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "years", value = "年代名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData yearsUpdate(@RequestParam("id") long id,
                                    @RequestParam("years") String years,
                                    @RequestParam("order") int order){
        // 年代名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_YEARS, years);
        if (inforDicList.size() > 0)    return ResponseData.success("修改失败，年代名称不能重复！",false);

        HzFixedInformationDicEntity oldFixedInformationDic = fixedInformationDicService.getById(id);
        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(id, years, new Date(), order);
        fixedInformationDicService.updateById(fixedInformationDic);
        Long oldId = oldFixedInformationDic.getId();
        if (oldId != id)
            // 同步临摹碑帖表记录修改
            copyingSteleCalligraphyService.updateAllRelatedSteleCalligraphyYears(oldId, years, id);
        return ResponseData.success("修改成功");
    }

    /**
     * 年代、书体、书家列表删除
     */
    @ApiOperation("年代、书体、书家列表删除")
    @PostMapping("/ysc/delete")
    public ResponseData yscDelete(@RequestBody Long[] ids){
        // 提取可删除的ids
        List<Long> allowRemoveIds = Stream.of(ids)
                .filter(id -> copyingSteleCalligraphyService.findOneById(id) == null)
                .collect(Collectors.toList());
        // 提取可删除的ids不为空才删除
        if (allowRemoveIds.size() > 0)
            fixedInformationDicService.removeByIds(allowRemoveIds);
        if (allowRemoveIds.size() != ids.length)
            return ResponseData.success("存在不能删除的列表项",false);
        return ResponseData.success("删除成功");
    }

    /**
     * 年代、书体、书家分页列表
     */
    @ApiOperation("年代、书体、书家分页列表")
    @GetMapping("/ysc/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "查询类别。1年代，2书体，3书家", paramType = "query", dataType = "Integer", allowableValues = "1,2,3", required = true),
            @ApiImplicitParam(name = "curPage", value = "当前页数", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", paramType = "query", dataType = "Integer", required = true)
    })
    public ResponseData<JSONObject> yscPage(@RequestParam("type") Integer type,
                                            @RequestParam("curPage") Integer curPage,
                                            @RequestParam("pageSize") Integer pageSize) {
        List<HzFixedInformationDicEntity> fixedInformationDics;
        JSONObject json = new JSONObject();

        switch (type){
            case 1 :
                fixedInformationDics = fixedInformationDicService.queryYears(curPage, pageSize, FixedInformationName.CO_ST_CALLI_YEARS);
                List<CopyingSteleCalligraphyYearsVo> copyingSteleCalligraphyYearsList = fixedInformationDics.stream()
                    .map(fixedInformationDic -> new CopyingSteleCalligraphyYearsVo(fixedInformationDic.getId(),
                            fixedInformationDic.getFixedInformationContent(),
                            fixedInformationDic.getUpdatetime(),
                            fixedInformationDic.getIorder()))
                    .collect(Collectors.toList());
                json.put("record",copyingSteleCalligraphyYearsList);
                json.put("total",fixedInformationDicService.queryFixedInformationDicsNum(FixedInformationName.CO_ST_CALLI_YEARS));
                break;
            case 2 :
                fixedInformationDics = fixedInformationDicService.queryYears(curPage, pageSize, FixedInformationName.CO_ST_CALLI_STYLE);
                List<CopyingSteleCalligraphyStyleVo> copyingSteleCalligraphyStyleList = fixedInformationDics.stream()
                    .map(fixedInformationDic -> new CopyingSteleCalligraphyStyleVo(fixedInformationDic.getId(),
                            fixedInformationDic.getFixedInformationContent(),
                            fixedInformationDic.getUpdatetime(),
                            fixedInformationDic.getIorder()))
                    .collect(Collectors.toList());
                json.put("record",copyingSteleCalligraphyStyleList);
                json.put("total",fixedInformationDicService.queryFixedInformationDicsNum(FixedInformationName.CO_ST_CALLI_STYLE));
                break;
            case 3 :
                fixedInformationDics = fixedInformationDicService.queryYears(curPage, pageSize, FixedInformationName.CO_ST_CALLI_CALLIGRAPHER);
                List<CopyingSteleCalligraphyCalligrapherVo> copyingSteleCalligraphyCalligrapherList = fixedInformationDics.stream()
                    .map(fixedInformationDic -> new CopyingSteleCalligraphyCalligrapherVo(fixedInformationDic.getId(),
                            fixedInformationDic.getFixedInformationContent(),
                            fixedInformationDic.getUpdatetime(),
                            fixedInformationDic.getIorder()))
                    .collect(Collectors.toList());
                json.put("record",copyingSteleCalligraphyCalligrapherList);
                json.put("total",fixedInformationDicService.queryFixedInformationDicsNum(FixedInformationName.CO_ST_CALLI_CALLIGRAPHER));
                break;
            default:
                json.put("record", null);
                json.put("total", 0);
                break;
        }
        json.put("size",pageSize);
        return ResponseData.success(json);
    }


    /**
     * 书体保存
     */
    @ApiOperation("书体保存")
    @PostMapping("/style/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "style", value = "书体名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData styleSave(@RequestParam("style") String style,
                                  @RequestParam("order") int order){
        // 名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_STYLE, style);
        if (inforDicList.size() > 0)    return ResponseData.success("保存失败，书体名称不能重复！",false);

        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(FixedInformationName.CO_ST_CALLI_STYLE, style, new Date(), order);
        fixedInformationDicService.save(fixedInformationDic);
        return ResponseData.success("保存成功");
    }

    /**
     * 书体修改
     */
    @ApiOperation("书体修改")
    @PostMapping("/style/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "书体id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "style", value = "书体名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData styleUpdate(@RequestParam("id") long id,
                                    @RequestParam("style") String style,
                                    @RequestParam("order") int order){
        // 名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_STYLE, style);
        if (inforDicList.size() > 0)    return ResponseData.success("修改失败，书体名称不能重复！",false);

        HzFixedInformationDicEntity oldFixedInformationDic = fixedInformationDicService.getById(id);
        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(id, style, new Date(), order);
        fixedInformationDicService.updateById(fixedInformationDic);
        Long oldId = oldFixedInformationDic.getId();
        if (oldId != id)
            // 同步临摹碑帖表记录修改
            copyingSteleCalligraphyService.updateAllRelatedSteleCalligraphyStyle(oldId, style, id);
        return ResponseData.success("修改成功");
    }

    /**
     * 书家保存
     */
    @ApiOperation("书家保存")
    @PostMapping("/calligrapher/save")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "书家名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData calligrapherSave(@RequestParam("name") String name,
                                         @RequestParam("order") int order){
        // 名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_CALLIGRAPHER, name);
        if (inforDicList.size() > 0)    return ResponseData.success("保存失败，书家名称不能重复！",false);
        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(FixedInformationName.CO_ST_CALLI_CALLIGRAPHER, name, new Date(), order);
        fixedInformationDicService.save(fixedInformationDic);
        return ResponseData.success("保存成功");
    }

    /**
     * 书家修改
     */
    @ApiOperation("书家修改")
    @PostMapping("/calligrapher/update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "书家id", paramType = "query", dataType = "Long", required = true),
            @ApiImplicitParam(name = "name", value = "书家名称", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "order", value = "顺序", paramType = "query", dataType = "int", required = true)
    })
    public ResponseData calligrapherUpdate(@RequestParam("id") long id,
                                           @RequestParam("name") String name,
                                           @RequestParam("order") int order){
        // 书家名称不能重复
        List<HzFixedInformationDicEntity> inforDicList = fixedInformationDicService.queryByNameAndContent(FixedInformationName.CO_ST_CALLI_CALLIGRAPHER, name);
        if (inforDicList.size() > 0)    return ResponseData.success("修改失败，书家名称不能重复！",false);

        HzFixedInformationDicEntity oldFixedInformationDic = fixedInformationDicService.getById(id);
        HzFixedInformationDicEntity fixedInformationDic = new HzFixedInformationDicEntity(id, name, new Date(), order);
        fixedInformationDicService.updateById(fixedInformationDic);
        Long oldId = oldFixedInformationDic.getId();
        if (oldId != id)
            // 同步临摹碑帖表记录修改
            copyingSteleCalligraphyService.updateAllRelatedSteleCalligraphyCalligrapher(oldId, name, id);
        return ResponseData.success("修改成功");
    }

}
